from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
import subprocess
import threading
import time

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///servers.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# 定义Server模型
class Server(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    hostname = db.Column(db.String(80), nullable=False)
    bmc_ip = db.Column(db.String(120), nullable=False)
    username = db.Column(db.String(80), nullable=False)
    password = db.Column(db.String(80), nullable=False)
    use_lanplus = db.Column(db.Boolean, nullable=False)
    powerstat = db.Column(db.String(20), nullable=False, default='Unknown')

# 初始化数据库
with app.app_context():
    db.create_all()

# 查询电源状态
def update_power_status():
    with app.app_context():
        while True:
            servers = Server.query.all()
            for server in servers:
                cmd = [
                    'ipmitool',
                    '-I', 'lanplus' if server.use_lanplus else 'lan',
                    '-H', server.bmc_ip,
                    '-U', server.username,
                    '-P', server.password,
                    'power', 'status'
                ]
                try:
                    result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
                    if 'Power is on' in result.stdout:
                        server.powerstat = 'power on'
                    elif 'Power is off' in result.stdout:
                        server.powerstat = 'power off'
                    else:
                        server.powerstat = 'Unknown'
                    db.session.commit()
                except subprocess.TimeoutExpired:
                    server.powerstat = 'Unknown'
            time.sleep(10)


# 启动后台线程更新电源状态
threading.Thread(target=update_power_status, daemon=True).start()

@app.route('/')
def index():
    servers = Server.query.all()
    return render_template('index.html', servers=servers)

@app.route('/add', methods=['GET', 'POST'])
def add_server():
    if request.method == 'POST':
        hostname = request.form['hostname']
        bmc_ip = request.form['bmc_ip']
        username = request.form['username']
        password = request.form['password']
        use_lanplus = request.form.get('use_lanplus') == 'on'
        new_server = Server(hostname=hostname, bmc_ip=bmc_ip, username=username, password=password, use_lanplus=use_lanplus)
        db.session.add(new_server)
        db.session.commit()
        return redirect(url_for('index'))
    return render_template('add_server.html')

@app.route('/edit/<int:id>', methods=['GET', 'POST'])
def edit_server(id):
    server = Server.query.get_or_404(id)
    if request.method == 'POST':
        server.hostname = request.form['hostname']
        server.bmc_ip = request.form['bmc_ip']
        server.username = request.form['username']
        server.password = request.form['password']
        server.use_lanplus = request.form.get('use_lanplus') == 'on'
        db.session.commit()
        return redirect(url_for('index'))
    return render_template('edit_server.html', server=server)

@app.route('/delete/<int:id>', methods=['POST'])
def delete_server(id):
    server = Server.query.get_or_404(id)
    db.session.delete(server)
    db.session.commit()
    return redirect(url_for('index'))

@app.route('/power/<int:id>/<action>')
def power_action(id, action):
    server = Server.query.get_or_404(id)
    if server:
        cmd = [
            'ipmitool',
            '-I', 'lanplus' if server.use_lanplus else 'lan',
            '-H', server.bmc_ip,
            '-U', server.username,
            '-P', server.password,
            'power', action
        ]
        try:
            subprocess.run(cmd, capture_output=True, text=True, timeout=10)
        except subprocess.TimeoutExpired:
            pass
    return redirect(url_for('index'))

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8900, debug=True)


